// 一种全新的原始数据类型 Symbol
// 创建一个独一无二的值
const s = Symbol();
console.log(s); // Symbol()
// 通过类型判断可以判断出是一个symbol类型
console.log(typeof s); // symbol
// 每一个Symbol都是独一无二的
console.log(Symbol() === Symbol()); // false
// 可以通过添加字符串来给Symbol添加标识 区分Symbol
console.log(Symbol("jack")); // Symbol(jack)
console.log(Symbol("tom")); // Symbol(tom)
// 即便传入的标识是一样的Symbol函数的结果也是全新的值
console.log(Symbol("bob") === Symbol("bob"));
// 对象可以使用symbol的值作为属性名
const name = Symbol();
const obj = {
    // 计算属性名的方式
    [name]: "jack",
    say() {
        console.log(this[name]);
    },
};
obj.say();
console.log(obj[name]);

// 如果要在全局复用一个Symbol的值可以使用for方法
// 接收一个字符串作为参数，相同的字符串就一定会有相同的结果
const s1 = Symbol.for("foo");
const s2 = Symbol.for("foo");
// 如果传入的不是字符串则方法内部会将传入值转换为字符串
console.log(Symbol.for(true) === Symbol.for("true")); // true
console.log(s1 === s2); // true

// 在Symbol类型中有很多内置的常量，作为内部方法的标识

const o = {
    // Symbol内置的常量toStringTag
    [Symbol.toStringTag]: "XObject",
    [Symbol()]: "symbol value",
    name: "bob",
};
// 对象的toString标签
console.log(o.toString()); // [object XObject]

// 以下遍历都不能拿到Symbol类型的属性名
for (let key in o) {
    console.log(key); // name
}
console.log(Object.keys(o)); // [ 'name' ]
console.log(JSON.stringify(o)); // {"name":"bob"}
// 所以Symbol类型的属性适合作为对象的私有属性

// Object.getOwnPropertySymbols()获取到的是所有Symbol类型的属性名
// Object.keys()获取到的是所有字符串类型的属性名
